package com.isyscore.os.metadata.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.isyscore.os.metadata.common.CommonService;
import com.isyscore.os.metadata.dao.MetricDimFilterMapper;
import com.isyscore.os.metadata.database.AbstractDatabase;
import com.isyscore.os.metadata.enums.FilterOperator;
import com.isyscore.os.metadata.model.dto.MetricDimFilterDTO;
import com.isyscore.os.metadata.model.entity.MetricDimFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Collections.emptyList;

/**
 * <p>
 * 保存指标的维度过滤条件,该表仅保存指标自身设定的过滤条件，对于派生指标需要进行级联查询 服务实现类
 * </p>
 *
 * @author wany
 * @since 2021-08-11
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class MetricDimFilterService extends CommonService<MetricDimFilterMapper, MetricDimFilter> {

    /**
     * 清除旧的过滤条件，存储指标的过滤条件
     */
    public void saveMetricFilter(Long metricId, List<MetricDimFilterDTO> filters) {
        //删除旧的条件
        this.deleteFilterByMetricId(metricId);
        if (filters != null) {
            //添加新条件
            for (MetricDimFilterDTO aFilter : filters) {
                MetricDimFilter filterModel = new MetricDimFilter();
                filterModel.setMetricRefId(metricId);
                BeanUtil.copyProperties(aFilter, filterModel);
                this.save(filterModel);
            }
        }
    }

    /**
     * 删除指定指标的所有过滤条件
     */
    public void deleteFilterByMetricId(Long metricId) {
        LambdaQueryWrapper<MetricDimFilter> qw = new LambdaQueryWrapper<>();
        qw.eq(MetricDimFilter::getMetricRefId, metricId);
        this.remove(qw);
    }

    /**
     * 获取指标的维度过滤条件
     */
    public List<MetricDimFilterDTO> getFilterByMetricId(Long metricId) {
        LambdaQueryWrapper<MetricDimFilter> qw = new LambdaQueryWrapper<>();
        qw.eq(MetricDimFilter::getMetricRefId, metricId);
        return this.list(qw).stream().map(filter -> {
            MetricDimFilterDTO filterDto = new MetricDimFilterDTO();
            BeanUtil.copyProperties(filter, filterDto);
            return filterDto;
        }).collect(Collectors.toList());
    }


    /**
     * 将用户自定义的filter翻译为sql条件
     */
    public String parseFilter2Sql(AbstractDatabase dbHelper, MetricDimFilterDTO filter) {
        StringBuilder condition = new StringBuilder();
        condition.append(dbHelper.escapeColName(filter.getDimColName()));
        condition.append(" ");
        condition.append(FilterOperator.valueOf(filter.getOperator()).getSymbol());
        condition.append(" ");
        if (filter.getOperator().equals(FilterOperator.in.getSymbol())) {
            condition.append("(");
            String[] values = filter.getDimConditionValue().split(",");
            for (String value : values) {
                condition.append(getDimConditionValue(value));
                condition.append(",");
            }
            condition.deleteCharAt(condition.lastIndexOf(","));
            condition.append(")");
        } else if (filter.getOperator().equals(FilterOperator.like.getSymbol())) {
            condition.append("'%").append(filter.getDimConditionValue()).append("%'");
        } else {
            condition.append(getDimConditionValue(filter.getDimConditionValue()));
        }
        return condition.toString();
    }

    public List<String> getUsedFilterColumnNames(Set<Long> metricIds) {
        if (metricIds == null || metricIds.isEmpty()) {
            return emptyList();
        }
        LambdaQueryWrapper<MetricDimFilter> qw = new LambdaQueryWrapper<>();
        qw.in(MetricDimFilter::getMetricRefId, metricIds);
        return this.list(qw).stream().map(MetricDimFilter::getDimColName).collect(Collectors.toList());
    }

    public void importData(List<MetricDimFilter> datas) {
        if (datas.isEmpty()) {
            return;
        }
        Set<Long> metricIds = datas.stream().map(MetricDimFilter::getMetricRefId).collect(Collectors.toSet());
        LambdaQueryWrapper<MetricDimFilter> qw = new LambdaQueryWrapper<>();
        qw.in(MetricDimFilter::getMetricRefId, metricIds);
        this.remove(qw);
        this.saveBatch(datas);
    }

    public List<MetricDimFilter> getDataByMetricIds(Set<Long> metricIds) {
        if (metricIds.isEmpty()) {
            return emptyList();
        }
        LambdaQueryWrapper<MetricDimFilter> qw = new LambdaQueryWrapper<>();
        qw.in(MetricDimFilter::getMetricRefId, metricIds);
        return this.list(qw);
    }

    private String getDimConditionValue(String value) {
        if (NumberUtil.isNumber(value)) {
            return value;
        } else {
            return "'" + value + "'";
        }
    }

}
